
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <linux/watchdog.h>
//dev/watchdog* 可以查看看门狗设备
// 通过ioctl 可以设置看门狗设备
//WDIOC_GETSUPPORT：获取查看支持哪些功能
//WDIOC_SETOPTIONS：开启或者关闭看门狗
//WDIOC_KEEPALIVE：喂狗操作

// 在options中存放了需要的信息
//struct watchdog_info {
//  __u32 options; /* Options the card/driver supports */
//  __u32 firmware_version; /* Firmware version of the card */
//  __u8 identity[32]; /* Identity of the board */
// };

//?当调用open打开看门狗设备时，即使程序中没有开启计时器，close时还是会自动启动
#define WDOG_DEV "/dev/watchdog"
int main(int argc,char* argv[])
{
    struct watchdog_info info;
    int timeout;
    int time;
    int fd;
    int op;
    if (2 != argc) {
        fprintf(stderr, "usage: %s <timeout>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    fd = open(WDOG_DEV,O_RDWR);
     if (0 > fd) {
        fprintf(stderr, "open error: %s: %s\n", WDOG_DEV, strerror(errno));
        exit(EXIT_FAILURE);
    }
     /* 打开之后看门狗计时器会开启、先停止它 */
    op = WDIOS_DISABLECARD;
    if (0 > ioctl(fd, WDIOC_SETOPTIONS, &op)) {
        fprintf(stderr, "ioctl error: WDIOC_SETOPTIONS: %s\n", strerror(errno));
        close(fd);
        exit(EXIT_FAILURE);
    }
    timeout = atoi(argv[1]);

    if(0 > ioctl(fd,WDIOC_SETTIMEOUT,&timeout)) {
        fprintf(stderr, "ioctl error: WDIOC_SETTIMEOUT: %s\n", strerror(errno));
        close(fd);
        exit(EXIT_FAILURE);
    }
    /* 开启看门狗计时器 */
    op = WDIOS_ENABLECARD;
    if (0 > ioctl(fd, WDIOC_SETOPTIONS, &op)) {
        fprintf(stderr, "ioctl error: WDIOC_SETOPTIONS: %s\n", strerror(errno));
        close(fd);
        exit(EXIT_FAILURE);
    }
    /* 喂狗 */
    // 当程序结束的时候停止喂狗  但是计时器并不会停止
    // 此时就会计时器溢出 发生复位重启
    time = (timeout * 1000 - 100) * 1000;//喂狗时间设置 us 微秒、在超时时间到来前 100ms 喂狗
    for ( ; ; ) {
        usleep(time);
        ioctl(fd, WDIOC_KEEPALIVE, NULL);
    }
}

